home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Peter's Final Project / jpeg-5b / rdcolmap.c < prev    next >
Text File  |  1994-09-22  |  7KB  |  254 lines

  1. /*
  2.  * rdcolmap.c
  3.  *
  4.  * Copyright (C) 1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file implements djpeg's "-map file" switch.  It reads a source image
  9.  * and constructs a colormap to be supplied to the JPEG decompressor.
  10.  *
  11.  * Currently, these file formats are supported for the map file:
  12.  *   GIF: the contents of the GIF's global colormap are used.
  13.  *   PPM (either text or raw flavor): the entire file is read and
  14.  *      each unique pixel value is entered in the map.
  15.  * Note that reading a large PPM file will be horrendously slow.
  16.  * Typically, a PPM-format map file should contain just one pixel
  17.  * of each desired color.  Such a file can be extracted from an
  18.  * ordinary image PPM file with ppmtomap(1).
  19.  *
  20.  * Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not
  21.  * currently implemented.
  22.  */
  23.  
  24. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  25.  
  26. #ifdef QUANT_2PASS_SUPPORTED    /* otherwise can't quantize to supplied map */
  27.  
  28. /* Portions of this code are based on the PBMPLUS library, which is:
  29. **
  30. ** Copyright (C) 1988 by Jef Poskanzer.
  31. **
  32. ** Permission to use, copy, modify, and distribute this software and its
  33. ** documentation for any purpose and without fee is hereby granted, provided
  34. ** that the above copyright notice appear in all copies and that both that
  35. ** copyright notice and this permission notice appear in supporting
  36. ** documentation.  This software is provided "as is" without express or
  37. ** implied warranty.
  38. */
  39.  
  40.  
  41. /*
  42.  * Add a (potentially) new color to the color map.
  43.  */
  44.  
  45. LOCAL void
  46. add_map_entry (j_decompress_ptr cinfo, int R, int G, int B)
  47. {
  48.   JSAMPROW colormap0 = cinfo->colormap[0];
  49.   JSAMPROW colormap1 = cinfo->colormap[1];
  50.   JSAMPROW colormap2 = cinfo->colormap[2];
  51.   int ncolors = cinfo->actual_number_of_colors;
  52.   int index;
  53.  
  54.   /* Check for duplicate color. */
  55.   for (index = 0; index < ncolors; index++) {
  56.     if (GETJSAMPLE(colormap0[index]) == R &&
  57.     GETJSAMPLE(colormap1[index]) == G &&
  58.     GETJSAMPLE(colormap2[index]) == B)
  59.       return;            /* color is already in map */
  60.   }
  61.  
  62.   /* Check for map overflow. */
  63.   if (ncolors >= (MAXJSAMPLE+1))
  64.     ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1));
  65.  
  66.   /* OK, add color to map. */
  67.   colormap0[ncolors] = (JSAMPLE) R;
  68.   colormap1[ncolors] = (JSAMPLE) G;
  69.   colormap2[ncolors] = (JSAMPLE) B;
  70.   cinfo->actual_number_of_colors++;
  71. }
  72.  
  73.  
  74. /*
  75.  * Extract color map from a GIF file.
  76.  */
  77.  
  78. LOCAL void
  79. read_gif_map (j_decompress_ptr cinfo, FILE * infile)
  80. {
  81.   int header[13];
  82.   int i, colormaplen;
  83.   int R, G, B;
  84.  
  85.   /* Initial 'G' has already been read by read_color_map */
  86.   /* Read the rest of the GIF header and logical screen descriptor */
  87.   for (i = 1; i < 13; i++) {
  88.     if ((header[i] = getc(infile)) == EOF)
  89.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  90.   }
  91.  
  92.   /* Verify GIF Header */
  93.   if (header[1] != 'I' || header[2] != 'F')
  94.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  95.  
  96.   /* There must be a global color map. */
  97.   if ((header[10] & 0x80) == 0)
  98.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  99.  
  100.   /* OK, fetch it. */
  101.   colormaplen = 2 << (header[10] & 0x07);
  102.  
  103.   for (i = 0; i < colormaplen; i++) {
  104.     R = getc(infile);
  105.     G = getc(infile);
  106.     B = getc(infile);
  107.     if (R == EOF || G == EOF || B == EOF)
  108.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  109.     add_map_entry(cinfo,
  110.           R << (BITS_IN_JSAMPLE-8),
  111.           G << (BITS_IN_JSAMPLE-8),
  112.           B << (BITS_IN_JSAMPLE-8));
  113.   }
  114. }
  115.  
  116.  
  117. /* Support routines for reading PPM */
  118.  
  119.  
  120. LOCAL int
  121. pbm_getc (FILE * infile)
  122. /* Read next char, skipping over any comments */
  123. /* A comment/newline sequence is returned as a newline */
  124. {
  125.   register int ch;
  126.   
  127.   ch = getc(infile);
  128.   if (ch == '#') {
  129.     do {
  130.       ch = getc(infile);
  131.     } while (ch != '\n' && ch != EOF);
  132.   }
  133.   return ch;
  134. }
  135.  
  136.  
  137. LOCAL unsigned int
  138. read_pbm_integer (j_decompress_ptr cinfo, FILE * infile)
  139. /* Read an unsigned decimal integer from the PPM file */
  140. /* Swallows one trailing character after the integer */
  141. /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
  142. /* This should not be a problem in practice. */
  143. {
  144.   register int ch;
  145.   register unsigned int val;
  146.   
  147.   /* Skip any leading whitespace */
  148.   do {
  149.     ch = pbm_getc(infile);
  150.     if (ch == EOF)
  151.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  152.   } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
  153.   
  154.   if (ch < '0' || ch > '9')
  155.     ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
  156.   
  157.   val = ch - '0';
  158.   while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
  159.     val *= 10;
  160.     val += ch - '0';
  161.   }
  162.   return val;
  163. }
  164.  
  165.  
  166. /*
  167.  * Extract color map from a PPM file.
  168.  */
  169.  
  170. LOCAL void
  171. read_ppm_map (j_decompress_ptr cinfo, FILE * infile)
  172. {
  173.   int c;
  174.   unsigned int w, h, maxval, row, col;
  175.   int R, G, B;
  176.  
  177.   /* Initial 'P' has already been read by read_color_map */
  178.   c = getc(infile);        /* save format discriminator for a sec */
  179.  
  180.   /* while we fetch the remaining header info */
  181.   w = read_pbm_integer(cinfo, infile);
  182.   h = read_pbm_integer(cinfo, infile);
  183.   maxval = read_pbm_integer(cinfo, infile);
  184.  
  185.   if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
  186.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  187.  
  188.   /* For now, we don't support rescaling from an unusual maxval. */
  189.   if (maxval != (unsigned int) MAXJSAMPLE)
  190.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  191.  
  192.   switch (c) {
  193.   case '3':            /* it's a text-format PPM file */
  194.     for (row = 0; row < h; row++) {
  195.       for (col = 0; col < w; col++) {
  196.     R = read_pbm_integer(cinfo, infile);
  197.     G = read_pbm_integer(cinfo, infile);
  198.     B = read_pbm_integer(cinfo, infile);
  199.     add_map_entry(cinfo, R, G, B);
  200.       }
  201.     }
  202.     break;
  203.  
  204.   case '6':            /* it's a raw-format PPM file */
  205.     for (row = 0; row < h; row++) {
  206.       for (col = 0; col < w; col++) {
  207.     R = pbm_getc(infile);
  208.     G = pbm_getc(infile);
  209.     B = pbm_getc(infile);
  210.     if (R == EOF || G == EOF || B == EOF)
  211.       ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  212.     add_map_entry(cinfo, R, G, B);
  213.       }
  214.     }
  215.     break;
  216.  
  217.   default:
  218.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  219.     break;
  220.   }
  221. }
  222.  
  223.  
  224. /*
  225.  * Main entry point from djpeg.c.
  226.  *  Input: opened input file (from file name argument on command line).
  227.  *  Output: colormap and actual_number_of_colors fields are set in cinfo.
  228.  */
  229.  
  230. GLOBAL void
  231. read_color_map (j_decompress_ptr cinfo, FILE * infile)
  232. {
  233.   /* Allocate space for a color map of maximum supported size. */
  234.   cinfo->colormap = (*cinfo->mem->alloc_sarray)
  235.     ((j_common_ptr) cinfo, JPOOL_IMAGE,
  236.      (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3);
  237.   cinfo->actual_number_of_colors = 0; /* initialize map to empty */
  238.  
  239.   /* Read first byte to determine file format */
  240.   switch (getc(infile)) {
  241.   case 'G':
  242.     read_gif_map(cinfo, infile);
  243.     break;
  244.   case 'P':
  245.     read_ppm_map(cinfo, infile);
  246.     break;
  247.   default:
  248.     ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
  249.     break;
  250.   }
  251. }
  252.  
  253. #endif /* QUANT_2PASS_SUPPORTED */
  254.